import { RangeOptions } from "./VirtualScrollList";

export type VirtualOption = {
  size: number;
  buffer: number;
  uniqueIds: string[];
  estimateSize: number;
};

export type updateType = (range: RangeOptions) => void;
export function initVirtual(
  param: VirtualOption,
  update: React.Dispatch<React.SetStateAction<RangeOptions>>
) {
  const range: RangeOptions = {
    start: 0,
    end: 0,
    padFront: 0,
    padBehind: 0,
  };
  function getPadFront() {
    return param.estimateSize * range.start;
  }
  function getPadBehind() {
    const lastIndex = param.uniqueIds.length - 1;
    return param.estimateSize * (lastIndex - range.end);
  }
  function updateRange(start: number, end: number) {
    range.start = start;
    range.end = end;
    range.padFront = getPadFront();
    range.padBehind = getPadBehind();
    let a = { ...range };
    update(() => a);
  }
  function checkRange(start: number, end: number) {
    const total = param.uniqueIds.length;
    const size = param.size;
    if (total < size) {
      start = 0;
      end = total - 1;
    } else if (end - start < size - 1) {
      start = end - size + 1;
    }

    updateRange(start, end);
  }

  checkRange(0, param.size - 1);
  let offsetValue = 0;
  function getScrollOvers() {
    return Math.floor(offsetValue / param.estimateSize);
  }
  function getEndByStart(start: number) {
    const computeEnd = start + param.size - 1;
    const end = Math.min(computeEnd, param.uniqueIds.length - 1);
    return end;
  }
  function handleFront() {
    const overs = getScrollOvers();
    if (overs > range.start) {
      return;
    }
    const start = Math.max(overs - param.buffer, 0);
    checkRange(start, getEndByStart(start));
  }
  function handleBehind() {
    const overs = getScrollOvers();
    if (overs < range.start + param.buffer) {
      return;
    }
    checkRange(overs, getEndByStart(overs));
  }
  function handleScroll(offset: number) {
    const direction = offset < offsetValue ? "FRONT" : "BEHIND";

    offsetValue = offset;
    if (direction === "FRONT") {
      handleFront();
    } else if (direction === "BEHIND") {
      handleBehind();
    }
  }

  return { handleScroll };
}
